from typing import Union, TypeVar, Generic, Sequence, Type

from fastapi import Query
from fastapi_pagination.bases import AbstractParams, AbstractPage, RawParams
from pydantic import BaseModel, Field, create_model

T = TypeVar("T")
C = TypeVar("C")


class PageParams(BaseModel, AbstractParams):
    pageNo: int = Query(1, ge=1, description='Page Number')
    pageSize: int = Query(20, gt=0, le=2000, description='Page Size')

    def to_raw_params(self) -> RawParams:
        offset = (self.pageNo - 1) * self.pageSize
        return RawParams(limit=self.pageSize, offset=offset)


class PageInationResult(AbstractPage[T], Generic[T]):
    """
    分页结果封装
        items: 返回集列表
        total: 结果总数
    """
    count: int
    pageNo: int
    pageSize: int
    lists: Sequence[T]

    __params_type__ = PageParams

    @classmethod
    def create(cls: Type['PageInationResult[T]'], items: Sequence[T], params: PageParams, **kwargs) \
            -> "PageInationResult[T]":
        total = kwargs.get('total', len(items))  # 从 kwargs 中获取 total 参数。如果 kwargs 中没有 total，则默认使用 len(items)
        return cls(lists=items, count=total, pageNo=params.pageNo, pageSize=params.pageSize)


class EmptyStrToNone:
    """空字符串替换类型
        针对非str类型，可传空字符串类型校验
    """

    @classmethod
    def __get_validators__(cls):
        yield cls.validate

    @classmethod
    def validate(cls, v, instance=None):
        if isinstance(v, str) and v.strip() == '':
            return None
        return v
